package performance.outer;

import dataset.Dataset;
import exception.SampleResultNotMatchException;
import scicalc.Calculate;

import java.util.HashMap;
import java.util.Map;

public class OuterPerformanceMeasure {
    private int a;
    private int b;
    private int c;
    private int d;
    private int m;

    public OuterPerformanceMeasure(int[] result, Dataset reference) {
//        Map<String, Integer> abcd = new HashMap<>();
//        abcd.put("a", 0);
//        abcd.put("b", 0);
//        abcd.put("c", 0);
//        abcd.put("d", 0);
        this.a = 0;
        this.b = 0;
        this.c = 0;
        this.d = 0;
        this.m = result.length;
        if (reference.shape[0] != result.length) {
            try {
                throw new SampleResultNotMatchException();
            } catch (SampleResultNotMatchException e) {
                e.printStackTrace();
            }
        } else {
            int len = result.length;
            for (int i = 0; i < len; i++) {
                for (int j = i + 1; j < len; j++) {
                    int num = 0;
                    if (result[i] == -1 || result[j] == -1)
                        continue;
                    if (result[i] == result[j])
                        num += 2;
                    if (reference.label[i] == reference.label[j])
                        num += 1;
                    switch (num) {
                        case 0:
                            this.d++;
                            break;
                        case 1:
                            this.c++;
                            break;
                        case 2:
                            this.b++;
                            break;
                        case 3:
                            this.a++;
                            break;
                    }
                }
            }
        }
    }

    public double JC() {
        return 1.0 * this.a / (this.a + this.b + this.c);
    }

    public double FMI() {
        return Calculate.sqrt(1.0 / (this.a + this.b) / (this.a + this.c)) * this.a;
    }

    public double RI() {
        return 2.0 * (this.a + this.b) / this.m / (this.m - 1);
    }

    public Map<String, Double> measures() {
        long start = System.nanoTime();
        Map<String, Double> map = new HashMap<>();
        map.put("JC", JC());
        map.put("FMI", FMI());
        map.put("RI", RI());
        long nTime = System.nanoTime() - start;
        double time = nTime / 1000 / 1e3;
        map.put("COST_TIME", time);
        return map;
    }

}
